package com.zmn.oms.business.impl.log;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.manager.mq.interfaces.ZmnMQSender;
import com.zmn.oms.business.interfaces.conf.distributereason.ConfOrderDistributeReasonBService;
import com.zmn.oms.business.interfaces.log.OrderLogNodeNoticeBService;
import com.zmn.oms.business.interfaces.work.OrderWorkBService;
import com.zmn.oms.common.constant.OrderConsts;
import com.zmn.oms.common.constant.OrderLogConsts;
import com.zmn.oms.common.constant.OrderVisitStatusConsts;
import com.zmn.oms.common.dto.OmsBaseOperator;
import com.zmn.oms.manager.utils.OmsMqTagConsts;
import com.zmn.oms.model.bo.conf.distribute.reason.ConfOrderDistributeReasonBO;
import com.zmn.oms.model.bo.order.OrderBO;
import com.zmn.oms.model.dto.acceptance.OrderWorkAcceptanceDTO;
import com.zmn.oms.model.dto.order.OrderDTO;
import com.zmn.oms.model.dto.track.OrderTrackDTO;
import com.zmn.oms.model.dto.track.OrderTrackDetailDTO;
import com.zmn.oms.model.dto.work.masterwork.ModifyDutyTimeDTO;
import com.zmn.oms.model.dto.work.modify.OrderDistributeDTO;
import com.zmn.oms.model.dto.work.modify.OrderMultipleVisitDTO;
import com.zmn.oms.model.dto.work.modify.OrderTurnDTO;
import com.zmn.oms.model.entity.changerecord.OrderChangeRecord;
import com.zmn.oms.model.entity.log.OrderLog;
import com.zmn.oms.model.entity.visit.OrderVisit;
import com.zmn.oms.model.entity.visit.OrderVisitQuery;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.services.interfaces.changerecord.OrderChangeRecordService;
import com.zmn.oms.services.interfaces.remark.OrderRemarkDetailService;
import com.zmn.oms.services.interfaces.visit.OrderVisitService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * 订单日志节点通知
 * 订单各节点日志 通知给其他系统
 * 暂不考虑使用广播方式
 * @author: LuJia
 * @version: v1.0
 * @since: 2020/04/16 16:56
 **/
@Service
@Slf4j
public class OrderLogNodeNoticeBServiceImpl implements OrderLogNodeNoticeBService {

    @Resource
    ZmnMQSender zmnMQSender;
    @Resource
    OrderWorkBService orderWorkBService;
    @Resource
    OrderVisitService orderVisitService;
    @Resource
    OrderChangeRecordService orderChangeRecordService;
    @Autowired
    private ConfOrderDistributeReasonBService confOrderDistributeReasonBService;
    @Autowired
    private OrderRemarkDetailService orderRemarkDetailService;

    @Value("${spring.mq.topic.performance:''}")
    String performanceTopic;

    @Value("${spring.profiles.active}")
    String activeProfile;

    /**
     * 通知节点
     * 取消，渠道取消，跟单，下单，确认，分单，分单撤回，派单，派单撤回，领单，联系用户，上门，服务完成，修改，工程师改预约时间, 天猫改预约时间，一键提醒，再次联系
     */
    static List<Integer> noticeTypes = Lists.newArrayList(
            OrderLogConsts.ORDER_LOG_TYPE_CHECKOUT,
            OrderLogConsts.ORDER_LOG_TYPE_ORDER_SUSPEND,
            OrderLogConsts.ORDER_LOG_TYPE_COMMENT,
            OrderLogConsts.ORDER_LOG_TYPE_CANCEL,
            OrderLogConsts.ORDER_LOG_TYPE_CHANNEL_CANCEL,
            OrderLogConsts.ORDER_LOG_TYPE_TRACK,
            OrderLogConsts.ORDER_LOG_TYPE_INPUT,
            OrderLogConsts.ORDER_LOG_TYPE_CONFIRM,
            OrderLogConsts.ORDER_LOG_TYPE_ASSIGN,
            OrderLogConsts.ORDER_LOG_TYPE_SERVICE_COMPLETE,
            OrderLogConsts.ORDER_LOG_TYPE_ASSIGN_BACK,
            OrderLogConsts.ORDER_LOG_TYPE_DISTRIBUTE,
            OrderLogConsts.ORDER_LOG_TYPE_DISTRIBUTE_BACK,
            OrderLogConsts.ORDER_LOG_TYPE_TAKE,
            OrderLogConsts.ORDER_LOG_TYPE_CONTACT_USER,
            OrderLogConsts.ORDER_LOG_TYPE_VISIT,
            OrderConsts.ORDER_OP_TYPE_SERVICE_COMPLETE,
            OrderLogConsts.ORDER_LOG_TYPE_COMPLETE,
            OrderLogConsts.ORDER_LOG_TYPE_UPDATE,
            OrderLogConsts.ORDER_LOG_TYPE_MASTER_MODIFY_DUTY_TIME,
            OrderLogConsts.ORDER_LOG_TYPE_TURN,
            OrderLogConsts.ORDER_LOG_TYPE_MODIFY_DUTY_TIME,
            OrderLogConsts.ORDER_LOG_TYPE_DEPOSIT_ACCEPTANCE,
            OrderLogConsts.ORDER_LOG_TYPE_ENGINEER_DEPOSIT_ACCEPTANCE,
            OrderLogConsts.ORDER_LOG_TYPE_AGAIN_VISIT,
            OrderLogConsts.ORDER_LOG_TYPE_CANCEL_AGAIN_VISIT,
            OrderLogConsts.ORDER_LOG_TYPE_ONE_CLICK_REMINDER,
            OrderLogConsts.ORDER_LOG_TYPE_CONTACT_USER_AGAIN,
            OrderLogConsts.ORDER_LOG_TYPE_APPLY_MULTIPLE_VISIT // 多次上门
    );

    /**
     * 预警系统使用，节点通知
     * @param orderLog
     * @param dbOrderWork
     * @param omsBaseOperator
     * @param proceed
     */
    @Override
    public void notice(OrderLog orderLog, OrderWork dbOrderWork, OmsBaseOperator omsBaseOperator, Object proceed) {

        if (!noticeTypes.contains(orderLog.getType())) {
            return;
        }

        // 跟单log 附带业务数据 特殊处理
        if (Objects.equals(orderLog.getType(), OrderLogConsts.ORDER_LOG_TYPE_TRACK)) {
            trackNotice(orderLog, dbOrderWork, omsBaseOperator);
            return;
        }

        // 多次上门申请
//        if (Objects.equals(orderLog.getType(), OrderLogConsts.ORDER_LOG_TYPE_APPLY_MULTIPLE_VISIT)) {
//            applyMultipleVisitNotice(orderLog, dbOrderWork, omsBaseOperator);
//            return;
//        }

        // 多次上门-拉修待件-定金确认
        if (Objects.equals(orderLog.getType(), OrderLogConsts.ORDER_LOG_TYPE_DEPOSIT_ACCEPTANCE)
                || Objects.equals(orderLog.getType(), OrderLogConsts.ORDER_LOG_TYPE_ENGINEER_DEPOSIT_ACCEPTANCE)) {
            confirmVisitNotice(orderLog, dbOrderWork, omsBaseOperator);
            return;
        }

        // 多次上门-拉修待件-再次上门
        if (Objects.equals(orderLog.getType(), OrderLogConsts.ORDER_LOG_TYPE_AGAIN_VISIT)) {
            againVisitNotice(orderLog, dbOrderWork, omsBaseOperator);
            return;
        }

        // 多次上门-拉修待件-取消上门
        if (Objects.equals(orderLog.getType(), OrderLogConsts.ORDER_LOG_TYPE_CANCEL_AGAIN_VISIT)) {
            cancelAgainVisitNotice(orderLog, dbOrderWork, omsBaseOperator);
            return;
        }

        // 下单log 附带业务数据 特殊处理
        if (Objects.equals(orderLog.getType(), OrderLogConsts.ORDER_LOG_TYPE_INPUT)) {
            inputNotice(orderLog, dbOrderWork, omsBaseOperator, proceed);
            return;
        }

        // 转单log 附带业务数据 特殊处理
        if (Objects.equals(orderLog.getType(), OrderLogConsts.ORDER_LOG_TYPE_TURN)) {
            turnNotice(orderLog, dbOrderWork, omsBaseOperator, proceed);
            return;
        }

        // 确认log 附带业务数据 特殊处理
        if (Objects.equals(orderLog.getType(), OrderLogConsts.ORDER_LOG_TYPE_CONFIRM)) {
            confirmNotice(orderLog, dbOrderWork, omsBaseOperator);
            return;
        }

        // 分单log 附带业务数据 特殊处理
        if (Objects.equals(orderLog.getType(), OrderLogConsts.ORDER_LOG_TYPE_ASSIGN)) {
            assignNotice(orderLog, dbOrderWork, omsBaseOperator);
            return;
        }

        // 派单log 附带业务数据 特殊处理
        if (Objects.equals(orderLog.getType(), OrderLogConsts.ORDER_LOG_TYPE_DISTRIBUTE)) {
            distributeNotice(orderLog, dbOrderWork, omsBaseOperator);
            return;
        }

        // 领单log 附带业务数据 特殊处理
        if (Objects.equals(orderLog.getType(), OrderLogConsts.ORDER_LOG_TYPE_TAKE)) {
            takeNotice(orderLog, dbOrderWork, omsBaseOperator);
            return;
        }

        // 挂起通知
        if ((Objects.equals(orderLog.getType(), OrderLogConsts.ORDER_LOG_TYPE_ORDER_SUSPEND))){
            suspendNotice(orderLog, dbOrderWork, omsBaseOperator);
            return;
        }

        // 联系用户log 附带业务数据 特殊处理
        if (Objects.equals(orderLog.getType(), OrderLogConsts.ORDER_LOG_TYPE_CONTACT_USER)) {
            contactNotice(orderLog, dbOrderWork, omsBaseOperator);
            return;
        }

        // 一键提醒
        if (Objects.equals(orderLog.getType(), OrderLogConsts.ORDER_LOG_TYPE_ONE_CLICK_REMINDER)) {
            oneClickReminderNotice(orderLog, dbOrderWork, omsBaseOperator);
            return;
        }

        // 已完成之后的 联系用户 -> 再次联系
        if (Objects.equals(orderLog.getType(), OrderLogConsts.ORDER_LOG_TYPE_CONTACT_USER_AGAIN)) {
            contactAgainNotice(orderLog, dbOrderWork, omsBaseOperator);
            return;
        }

        // 修改log 附带业务数据 特殊处理
        if (Objects.equals(orderLog.getType(), OrderLogConsts.ORDER_LOG_TYPE_UPDATE)) {
            updateNotice(orderLog, dbOrderWork, omsBaseOperator);
            return;
        }

        // 工程师改约时间log 附带业务数据 特殊处理
        if (Objects.equals(orderLog.getType(), OrderLogConsts.ORDER_LOG_TYPE_MASTER_MODIFY_DUTY_TIME)) {
            modifyDutyTimeNotice(orderLog, dbOrderWork, omsBaseOperator);
            return;
        }

        // TMALL改约时间log 附带业务数据 特殊处理
        if (Objects.equals(orderLog.getType(), OrderLogConsts.ORDER_LOG_TYPE_MODIFY_DUTY_TIME)) {
            modifyDutyTimeNotice(orderLog, dbOrderWork, omsBaseOperator);
            return;
        }

        // 校验dbOrderWork
        if (Objects.isNull(dbOrderWork)) {
            log.error("#oms#OrderLogNodeNotice dbOrderWork is null msg:{}", orderLog);
            return;
        }

        // 其他log 附带业务数据 特殊处理
        long operateTime = DateUtil.getNow().getTime();

        Integer bizType = dbOrderWork.getBizType();

        sendMessage(orderLog.getWorkId(), orderLog.getOrderId(), orderLog.getType(), dbOrderWork.getPlatWork(), operateTime, null, bizType);
    }


    /**
     * 转单通知
     * @param orderLog
     * @param dbOrderWork
     * @param omsBaseOperator
     * @param proceed
     */
    private void turnNotice(OrderLog orderLog, OrderWork dbOrderWork, OmsBaseOperator omsBaseOperator, Object proceed) {

        long distributeTime = DateUtil.getNow().getTime();

        Integer afterPlatWork = null;
        Integer beforePlatWork = null;

        if (omsBaseOperator instanceof OrderTurnDTO) {
            OrderTurnDTO orderTurnDTO = (OrderTurnDTO) omsBaseOperator;
            afterPlatWork = orderTurnDTO.getPlatWork();
        }

        // 预约时间
        if (Objects.nonNull(dbOrderWork) && Objects.nonNull(dbOrderWork.getPlatWork())) {
            beforePlatWork = dbOrderWork.getPlatWork();
        } else {
            beforePlatWork = afterPlatWork;
        }

        // 转单前后平台
        JSONObject turn = new JSONObject();
        turn.put("beforePlatWork", beforePlatWork);
        turn.put("afterPlatWork", afterPlatWork);


        Integer bizType = dbOrderWork.getBizType();
        sendMessage(orderLog.getWorkId(), orderLog.getOrderId(), orderLog.getType(), dbOrderWork.getPlatWork(), distributeTime, turn, bizType);
    }

    /**
     * 录单 通知
     * @param orderLog
     * @param dbOrderWork
     * @param omsBaseOperator
     * @param proceed
     */
    private void inputNotice(OrderLog orderLog, OrderWork dbOrderWork, OmsBaseOperator omsBaseOperator, Object proceed) {

        // 是否需要预付
        OrderWork orderWork = null;
        if (proceed instanceof OrderBO) {
            OrderBO orderBO = (OrderBO) proceed;
            orderWork = orderBO.getOrderWork();
        }

        // 需要预付
        JSONObject input = new JSONObject();
        if (Objects.nonNull(orderWork)) {
            boolean waitPrePay = orderWorkBService.isWaitPrePay(orderWork);
            input.put("waitPrepay", waitPrePay);

            Date dutyTime = orderWork.getDutyTime();
            if (Objects.nonNull(dutyTime)) {
                input.put("dutyTime", dutyTime.getTime());
            }

            Integer bizType = orderWork.getBizType();

            sendMessage(orderLog.getWorkId(), orderLog.getOrderId(), orderLog.getType(), orderWork.getPlat(), DateUtil.getNow().getTime(), input, bizType);

        }
        else {
            log.error("#performance#inputNotice orderWork is null");
        }
    }

    /**
     * 修改预约时间 通知
     * @param orderLog
     * @param dbOrderWork
     * @param omsBaseOperator
     */
    private void modifyDutyTimeNotice(OrderLog orderLog, OrderWork dbOrderWork, OmsBaseOperator omsBaseOperator) {

        long distributeTime = DateUtil.getNow().getTime();

        Date dutyTime = null;

        // dutyTime
        // 优先取 操作对象中的预约时间 其次取db中的预约时间
        if (omsBaseOperator instanceof ModifyDutyTimeDTO) {
            ModifyDutyTimeDTO modifyDutyTimeDTO = (ModifyDutyTimeDTO) omsBaseOperator;
            dutyTime = modifyDutyTimeDTO.getDutyTime();
        }

        JSONObject modifyDutyTime = new JSONObject();
        if (Objects.nonNull(dutyTime)) {
            modifyDutyTime.put("dutyTime", dutyTime.getTime());
        }
        Integer bizType = dbOrderWork.getBizType();
        sendMessage(orderLog.getWorkId(), orderLog.getOrderId(), orderLog.getType(), dbOrderWork.getPlatWork(), distributeTime, modifyDutyTime, bizType);
    }

    /**
     * 修改通知
     * @param orderLog
     * @param dbOrderWork
     * @param omsBaseOperator
     */
    private void updateNotice(OrderLog orderLog, OrderWork dbOrderWork, OmsBaseOperator omsBaseOperator) {

        long distributeTime = DateUtil.getNow().getTime();

        Date dutyTime = null;

        // dutyTime
        // 优先取 操作对象中的预约时间 其次取db中的预约时间
        if (omsBaseOperator instanceof OrderDTO) {
            OrderDTO orderDTO = (OrderDTO) omsBaseOperator;
            dutyTime = orderDTO.getOrderWork().getDutyTime();
        }

        // 预约时间
        Date dbDutyTime = dbOrderWork.getDutyTime();
        if (Objects.isNull(dutyTime)) {
            dutyTime = dbDutyTime;
        }

        // 从 无到有传 or 时间变更 传
        JSONObject update = new JSONObject();
        if (Objects.isNull(dbDutyTime) && Objects.nonNull(dutyTime)) {
            update.put("dutyTime", dutyTime.getTime());
        } else if (Objects.nonNull(dutyTime) && Objects.nonNull(dbDutyTime) && dutyTime.getTime() != dbDutyTime.getTime()) {
            update.put("dutyTime", dutyTime.getTime());
        }
        Integer bizType = dbOrderWork.getBizType();
        sendMessage(orderLog.getWorkId(), orderLog.getOrderId(), orderLog.getType(), dbOrderWork.getPlatWork(), distributeTime, update, bizType);
    }

    /**
     * 联系用户通知
     * @param orderLog
     * @param dbOrderWork
     * @param omsBaseOperator
     */
    private void contactNotice(OrderLog orderLog, OrderWork dbOrderWork, OmsBaseOperator omsBaseOperator) {

        long distributeTime = DateUtil.getNow().getTime();

        // masterId， distributeTime
        JSONObject contact = new JSONObject();
        if (Objects.nonNull(dbOrderWork)) {
            contact.put("masterId", dbOrderWork.getMasterId());

            if (Objects.nonNull(dbOrderWork.getDistributeTime())) {
                contact.put("distributeTime", dbOrderWork.getDistributeTime().getTime());
            }
        }
        Integer bizType = dbOrderWork.getBizType();
        sendMessage(orderLog.getWorkId(), orderLog.getOrderId(), orderLog.getType(), dbOrderWork.getPlatWork(), distributeTime, contact, bizType);
    }

    /**
     * 一键提醒通知
     * @param orderLog
     * @param dbOrderWork
     * @param omsBaseOperator
     */
    private void oneClickReminderNotice(OrderLog orderLog, OrderWork dbOrderWork, OmsBaseOperator omsBaseOperator) {
        long now = DateUtil.getNow().getTime();
        JSONObject contact = new JSONObject();
        if (Objects.nonNull(dbOrderWork)) {
            contact.put("masterId", dbOrderWork.getMasterId());
        }
        Integer bizType = dbOrderWork.getBizType();
        sendMessage(orderLog.getWorkId(), orderLog.getOrderId(), orderLog.getType(), dbOrderWork.getPlatWork(), now, contact, bizType);
    }

    /**
     * 再次联系通知
     * @param orderLog
     * @param dbOrderWork
     * @param omsBaseOperator
     */
    private void contactAgainNotice(OrderLog orderLog, OrderWork dbOrderWork, OmsBaseOperator omsBaseOperator) {
        long now = DateUtil.getNow().getTime();
        JSONObject contact = new JSONObject();
        if (Objects.nonNull(dbOrderWork)) {
            contact.put("masterId", dbOrderWork.getMasterId());
        }
        Integer bizType = dbOrderWork.getBizType();
        sendMessage(orderLog.getWorkId(), orderLog.getOrderId(), orderLog.getType(), dbOrderWork.getPlatWork(), now, contact, bizType);
    }

    /**
     * 领单通知
     * @param orderLog
     * @param dbOrderWork
     * @param omsBaseOperator
     */
    private void takeNotice(OrderLog orderLog, OrderWork dbOrderWork, OmsBaseOperator omsBaseOperator) {

        long distributeTime = DateUtil.getNow().getTime();

        // masterId， distributeTime
        JSONObject take = new JSONObject();
        if (Objects.nonNull(dbOrderWork)) {
            take.put("masterId", dbOrderWork.getMasterId());

            if (Objects.nonNull(dbOrderWork.getDistributeTime())) {
                take.put("distributeTime", dbOrderWork.getDistributeTime().getTime());
            }
        }
        Integer bizType = dbOrderWork.getBizType();
        sendMessage(orderLog.getWorkId(), orderLog.getOrderId(), orderLog.getType(), dbOrderWork.getPlatWork(), distributeTime, take, bizType);
    }

    /**
     * 挂起通知
     * @param orderLog 
     * @param dbOrderWork 
     * @param omsBaseOperator 
     * @return void
     * @author wangxiaokun
     */
    private void suspendNotice(OrderLog orderLog, OrderWork dbOrderWork, OmsBaseOperator omsBaseOperator){
        long suspendTime = DateUtil.getNow().getTime();
        Integer bizType = dbOrderWork.getBizType();
        sendMessage(orderLog.getWorkId(), orderLog.getOrderId(), orderLog.getType(), dbOrderWork.getPlatWork(), suspendTime, null, bizType);
    }

    /**
     * 派单通知
     * @param orderLog
     * @param dbOrderWork
     * @param omsBaseOperator
     */
    private void distributeNotice(OrderLog orderLog, OrderWork dbOrderWork, OmsBaseOperator omsBaseOperator) {

        OrderDistributeDTO distributeDTO = (OrderDistributeDTO) omsBaseOperator;
        long distributeTime = Optional.ofNullable(distributeDTO.getDistributeDate()).orElse(DateUtil.getNow()).getTime();

        // masterId， distributeTime(当前派单时间)
        JSONObject distribute = new JSONObject();
        if (Objects.nonNull(dbOrderWork)) {
            distribute.put("masterId", distributeDTO.getMasterId());
            distribute.put("distributeTime", distributeTime);
            OrderChangeRecord record = orderChangeRecordService.getChangeRecordByOrderIdSrcMaster(dbOrderWork.getOrderId());
            distribute.put("distributeCount", record.getDistributeCount());
            if (NumberUtil.isNotNullOrZero(distributeDTO.getDistributeReasonId())) {
                // 兜底处理 改派次数实际大于0 但只查询出首次的情况
                if (NumberUtil.isNullOrZero(record.getDistributeCount())) {
                    distribute.put("distributeCount", record.getDistributeCount() + 1);
                }
                ConfOrderDistributeReasonBO reasonBO = confOrderDistributeReasonBService.getConfOrderDistributeReasonById(distributeDTO.getDistributeReasonId());
                distribute.put("countEnable", reasonBO.getCountEnable());
                distribute.put("originalMasterId", distributeDTO.getOriginalMasterId());
            }

        }
        Integer bizType = dbOrderWork.getBizType();
        sendMessage(orderLog.getWorkId(), orderLog.getOrderId(), orderLog.getType(), dbOrderWork.getPlatWork(), distributeTime, distribute, bizType);
    }

    /**
     * 分单通知
     * @param orderLog
     * @param dbOrderWork
     * @param omsBaseOperator
     */
    private void assignNotice(OrderLog orderLog, OrderWork dbOrderWork, OmsBaseOperator omsBaseOperator) {
        JSONObject confirm = new JSONObject();
        if (Objects.nonNull(dbOrderWork) && Objects.nonNull(dbOrderWork.getDutyTime())) {
            if (Objects.nonNull(dbOrderWork.getDutyTime())) {
                confirm.put("dutyTime", dbOrderWork.getDutyTime().getTime());
            }
        }
        Integer bizType = dbOrderWork.getBizType();
        sendMessage(orderLog.getWorkId(), orderLog.getOrderId(), orderLog.getType(), dbOrderWork.getPlatWork(), DateUtil.getNow().getTime(), confirm, bizType);
    }

    /**
     * 确认通知
     * @param orderLog
     * @param dbOrderWork
     * @param omsBaseOperator
     */
    private void confirmNotice(OrderLog orderLog, OrderWork dbOrderWork, OmsBaseOperator omsBaseOperator) {

        Date dutyTime = null;

        // 优先取 操作对象中的预约时间 其次取db中的预约时间
        if (omsBaseOperator instanceof OrderDTO) {
            OrderDTO orderDTO = (OrderDTO) omsBaseOperator;
            dutyTime = orderDTO.getOrderWork().getDutyTime();
        }

        // 预约时间
        Date dbDutyTime = dbOrderWork.getDutyTime();
        if (Objects.isNull(dutyTime)) {
            dutyTime = dbDutyTime;
        }

        // 从 无到有传 or 时间变更 传
        JSONObject confirm = new JSONObject();
        if (Objects.isNull(dbDutyTime) && Objects.nonNull(dutyTime)) {
            confirm.put("dutyTime", dutyTime.getTime());
        } else if (Objects.nonNull(dutyTime) && Objects.nonNull(dbDutyTime) && dutyTime.getTime() != dbDutyTime.getTime()) {
            confirm.put("dutyTime", dutyTime.getTime());
        }
        Integer bizType = dbOrderWork.getBizType();
        sendMessage(orderLog.getWorkId(), orderLog.getOrderId(), orderLog.getType(), dbOrderWork.getPlatWork(), DateUtil.getNow().getTime(), confirm, bizType);
    }

    /**
     * 跟单通知
     * @param orderLog
     * @param dbOrderWork
     * @param omsBaseOperator
     */
    private void trackNotice(OrderLog orderLog, OrderWork dbOrderWork, OmsBaseOperator omsBaseOperator) {

        // 优先取 操作对象中的预约时间 其次取db中的预约时间
        if (!(omsBaseOperator instanceof OrderTrackDTO)) {
            log.error("#oms#trackNotice 跟单日志 跟单DTO类型不匹配");
            return;
        }

        OrderTrackDTO orderTrackDTO = (OrderTrackDTO) omsBaseOperator;

        long operateTime = DateUtil.getNow().getTime();

        List<OrderTrackDetailDTO> detailDTOList = orderTrackDTO.getDetailDTOList();
        detailDTOList.forEach(detailDTO -> {

            Long trackId = detailDTO.getTrackId();
            String resultContent = detailDTO.getResultContent();
            Integer deleted = detailDTO.getDeleted();
            Integer level = detailDTO.getLevel();

            JSONObject track;
            if (Objects.equals(deleted, GlobalConsts.YES)) {
                track = buildTrack(trackId, level, 3);
            } else if (Objects.equals(detailDTO.getIsNew(), GlobalConsts.YES)) {
                track = buildTrack(trackId, level, 1);
            } else if (Objects.nonNull(trackId) && StringUtil.isNotBlank(resultContent)) {
                track = buildTrack(trackId, level, 2);
            } else {
                log.error("#oms#trackNotice#{} 未知情况：{}", orderLog.getOrderId(), orderTrackDTO);
                return;
            }
            Integer bizType = dbOrderWork.getBizType();
            sendMessage(orderLog.getWorkId(), orderLog.getOrderId(), orderLog.getType(), dbOrderWork.getPlatWork(), operateTime, track, bizType);
        });
    }

    /**
     * 多次上门申请消息
     * @param orderLog
     * @param dbOrderWork
     * @param omsBaseOperator
     */
    private void applyMultipleVisitNotice(OrderLog orderLog, OrderWork dbOrderWork, OmsBaseOperator omsBaseOperator) {

        // 申请多次上门
        if (!(omsBaseOperator instanceof OrderMultipleVisitDTO)) {
            return;
        }

        OrderMultipleVisitDTO multipleVisitDTO = (OrderMultipleVisitDTO) omsBaseOperator;
        if (Objects.isNull(multipleVisitDTO)) {
            return;
        }

        OrderVisitQuery query = new OrderVisitQuery();
        query.setVisitId(multipleVisitDTO.getVisitId());
        query.setOrderId(multipleVisitDTO.getOrderId());
        OrderVisit orderVisit = orderVisitService.findOrderVisitByQuerySrcMaster(query);
        log.info("#oms#confirmVisitNotice 申请多次 上门信息：【{}】", JSON.toJSONString(orderVisit));
        // 不是拉修待件，返回
        if (Objects.equals(orderVisit.getVisitType(), OrderVisitStatusConsts.ORDER_VISIT_TYPE_OTHER)) {
            return;
        }

        JSONObject data = new JSONObject();
        data.put("masterId", orderVisit.getMasterId());
        data.put("visitType", orderVisit.getVisitType());
        data.put("expectVisitTime", orderVisit.getExpectVisitTime());
        data.put("visitId", orderVisit.getVisitId());
        Long operateTime = Optional.ofNullable(omsBaseOperator.getOperateTime()).orElse(DateUtil.getNow()).getTime();
        sendMessage(orderLog.getWorkId(), orderLog.getOrderId(), OrderLogConsts.ORDER_LOG_TYPE_APPLY_MULTIPLE_VISIT, dbOrderWork.getPlatWork(), operateTime, data, dbOrderWork.getBizType());
    }

    /**
     * 确认再次上门(确认定金后)
     * @param orderLog
     * @param dbOrderWork
     * @param omsBaseOperator
     */
    private void confirmVisitNotice(OrderLog orderLog, OrderWork dbOrderWork, OmsBaseOperator omsBaseOperator) {

        // 不是定金确认验收DTO返回
        if (!(omsBaseOperator instanceof OrderWorkAcceptanceDTO)) {
            log.error("#oms#confirmVisitNotice 定金确认日志 定金确认DTO类型不匹配");
            return;
        }

        OrderWorkAcceptanceDTO acceptanceDTO = (OrderWorkAcceptanceDTO) omsBaseOperator;
        if (Objects.isNull(acceptanceDTO) || Objects.isNull(acceptanceDTO.getDbOrderWorkAcceptance())
                || NumberUtil.isNullOrZero(acceptanceDTO.getDbOrderWorkAcceptance().getVisitId())) {
            log.info("#oms#confirmVisitNotice 定金确认日志 未找到上门信息：【{}】", JSON.toJSONString(acceptanceDTO));
            return;
        }

        OrderVisitQuery query = new OrderVisitQuery();
        query.setVisitId(acceptanceDTO.getDbOrderWorkAcceptance().getVisitId());
        query.setOrderId(acceptanceDTO.getOrderId());
        OrderVisit orderVisit = orderVisitService.findOrderVisitByQuerySrcMaster(query);
        log.info("#oms#confirmVisitNotice 定金确认日志 上门信息：【{}】", JSON.toJSONString(orderVisit));
        // 不是拉修待件，返回
        if (Objects.equals(orderVisit.getVisitType(), OrderVisitStatusConsts.ORDER_VISIT_TYPE_OTHER)) {
            return;
        }

        JSONObject data = new JSONObject();
        data.put("masterId", orderVisit.getMasterId());
        data.put("visitType", orderVisit.getVisitType());
        data.put("expectVisitTime", orderVisit.getExpectVisitTime());
        data.put("visitId", orderVisit.getVisitId());
        Long operateTime = Optional.ofNullable(acceptanceDTO.getOperateTime()).orElse(DateUtil.getNow()).getTime();
        sendMessage(orderLog.getWorkId(), orderLog.getOrderId(), OrderLogConsts.ORDER_LOG_TYPE_DEPOSIT_ACCEPTANCE, dbOrderWork.getPlatWork(), operateTime, data, dbOrderWork.getBizType());
    }

    /**
     * 再次上门
     * @param orderLog
     * @param dbOrderWork
     * @param omsBaseOperator
     */
    private void againVisitNotice(OrderLog orderLog, OrderWork dbOrderWork, OmsBaseOperator omsBaseOperator) {

        // 不是再次上门DTO返回
        if (!(omsBaseOperator instanceof OrderMultipleVisitDTO)) {
            log.error("#oms#againVisitNotice 再次上门日志 再次上门DTO类型不匹配");
            return;
        }

        OrderMultipleVisitDTO visitDTO = (OrderMultipleVisitDTO) omsBaseOperator;

        OrderVisit orderVisit = visitDTO.getDbOrderVisit();
        // 不是拉修待件，返回
        if (Objects.equals(orderVisit.getVisitType(), OrderVisitStatusConsts.ORDER_VISIT_TYPE_OTHER)) {
            return;
        }
        JSONObject data = new JSONObject();
        data.put("masterId", orderVisit.getMasterId());
        data.put("visitType", orderVisit.getVisitType());
        data.put("expectVisitTime", orderVisit.getExpectVisitTime());
        data.put("visitId", orderVisit.getVisitId());
        Long operateTime = Optional.ofNullable(visitDTO.getOperateTime()).orElse(DateUtil.getNow()).getTime();
        sendMessage(orderLog.getWorkId(), orderLog.getOrderId(), orderLog.getType(), dbOrderWork.getPlatWork(), operateTime, data, dbOrderWork.getBizType());
    }

    /**
     * 取消再次上门
     * @param orderLog
     * @param dbOrderWork
     * @param omsBaseOperator
     */
    private void cancelAgainVisitNotice(OrderLog orderLog, OrderWork dbOrderWork, OmsBaseOperator omsBaseOperator) {

        // 不是取消再次上门DTO返回
        if (!(omsBaseOperator instanceof OrderMultipleVisitDTO)) {
            log.error("#oms#cancelAgainVisitNotice 取消再次上门日志 取消再次上门DTO类型不匹配");
            return;
        }

        OrderMultipleVisitDTO visitDTO = (OrderMultipleVisitDTO) omsBaseOperator;

        OrderVisit orderVisit = visitDTO.getDbOrderVisit();
        // 不是拉修待件，返回
        if (Objects.equals(orderVisit.getVisitType(), OrderVisitStatusConsts.ORDER_VISIT_TYPE_OTHER)) {
            return;
        }
        JSONObject data = new JSONObject();
        data.put("masterId", orderVisit.getMasterId());
        data.put("visitType", orderVisit.getVisitType());
        data.put("expectVisitTime", orderVisit.getExpectVisitTime());
        data.put("visitId", orderVisit.getVisitId());
        Long operateTime = Optional.ofNullable(visitDTO.getOperateTime()).orElse(DateUtil.getNow()).getTime();
        sendMessage(orderLog.getWorkId(), orderLog.getOrderId(), orderLog.getType(), dbOrderWork.getPlatWork(), operateTime, data, dbOrderWork.getBizType());
    }

    /**
     * 构建跟单消息体
     * @param trackId
     * @param trackLevel
     * @param trackOperateType 跟单操作类型 1 新增 2完成 3删除
     * @return
     */
    private JSONObject buildTrack(Long trackId, Integer trackLevel, Integer trackOperateType) {
        JSONObject track = new JSONObject();
        track.put("trackId", trackId);
        track.put("trackLevel", trackLevel);
        track.put("trackOperateType", trackOperateType);
        return track;
    }

    /**
     * 发送消息
     * @param workId
     * @param orderId
     * @param logType
     * @param plat
     * @param operateTime
     * @param bizData
     * @param bizType
     * @return
     */
    private void sendMessage(Long workId, Long orderId, Integer logType, Integer plat, Long operateTime, JSONObject bizData, Integer bizType) {

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("orderId", orderId);
        jsonObject.put("workId", workId);
        jsonObject.put("plat", plat);
        jsonObject.put("logType", logType);
        jsonObject.put("operateTime", operateTime);
        jsonObject.put("bizType", bizType);
        jsonObject.put("bizData", bizData);

        // 延迟三秒执行 防止未提交事物 or 同步到es
        long time = System.currentTimeMillis() + 3000;
        String message = JSON.toJSONString(jsonObject);
        String key = String.format("%s-%s", orderId, logType);

//        String noticeProfile = "dev,uat,test";
        String noticeProfile = "dev,uat,test,prod,test2";

        if (StringUtils.contains(noticeProfile, activeProfile)) {
            log.info("通知绩效系统：key:{},message:【{}】", key, message);
            zmnMQSender.sendWithStartDeliverTime(performanceTopic, OmsMqTagConsts.ZMN_TOPIC_PERFORMANCE_ORDER_LOG_NOTICE, key, message, time);
        }
    }

}
